﻿// -- MVC4WPF
// -- Copyright © 2009 Information Control Corporation
// -- Revision History:
// -- Version 0.9.0.0 First codeplex release  - Stephen Giffin

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;

namespace MVC4WPF.Automation.VisualStudio.Dialog
{
    /// <summary>
    /// Interaction logic for ContractDialog.xaml
    /// </summary>
    public partial class ContractDialog : Window, IContractDialog, INotifyPropertyChanged
    {
        #region Fields

        #endregion

        #region Constructor

        /// <summary>
        /// Public constuctor for the ContractDialog class.
        /// </summary>
        public ContractDialog()
        {
            this.InitializeComponent();

            //listen to the property changed event on the property bag
            this.ViewPropertyBag.PropertyChanged += new PropertyChangedEventHandler(ViewPropertyBag_PropertyChanged);
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// This event handler listens to the property changed event on the view property bag.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">Argument provided by the sender.</param>
        void ViewPropertyBag_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            //if the contract type is the type that changed
            if (e.PropertyName.Equals("ContractType"))
            {
                //change the brush associated with the background of the dialog based on the type passed in.
                switch (this.ViewPropertyBag.ContractType)
                {
                    case MVC4WPF.Automation.Data.MVCItemType.ViewWindowContract:
                    case MVC4WPF.Automation.Data.MVCItemType.ViewPageContract:
                    case MVC4WPF.Automation.Data.MVCItemType.ViewUserControlContract:
                        this.BackgroundBrush = this.FindResource("ViewBrush") as Brush;
                        break;
                    case MVC4WPF.Automation.Data.MVCItemType.WindowControllerContract:
                    case MVC4WPF.Automation.Data.MVCItemType.PageControllerContract:
                    case MVC4WPF.Automation.Data.MVCItemType.UserControlControllerContract:
                        this.BackgroundBrush = this.FindResource("ControllerBrush") as Brush;
                        break;
                    case MVC4WPF.Automation.Data.MVCItemType.ModelContract:
                        this.BackgroundBrush = this.FindResource("ModelBrush") as Brush;
                        break;
                    default:
                        //if an unexpected type came in, just use the default contract brush
                        this.BackgroundBrush = this.FindResource("ContractBrush") as Brush;
                        break;
                }
            }
        }

        /// <summary>
        /// The Select Button click handler
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument provided by the sender</param>
        private void ButtonSelect_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //Letting external processing occur.
            OnSelected();

            //If the property bag expander is open and the user hasn't selected a property bag
            if (ViewPropertyBag.ContractUsesPropertyBag && ViewPropertyBag.SelectedPropertyBag == null)
            {
                //prompt the user to select a property bag
                MessageBox.Show("Please select a property bag to continue.", "PropertyBag Not Selected", MessageBoxButton.OK, MessageBoxImage.Asterisk);
                return;
            }
            //everything is good, return a success condition and close the dialog window
            this.DialogResult = true;
            this.Close();
        }

        /// <summary>
        /// The Cancel Button click handler
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">Argument provided by the sender</param>
        private void ButtonCancel_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //cancel was clicked, return the default cancel condition and close the dialog window
            this.Close();
        }

        /// <summary>
        /// The Property Bag Expander expanded event handler
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument provided by the sender</param>
        private void ExpanderPropertyBag_Expanded(object sender, RoutedEventArgs e)
        {
            //set a flag
            this.ViewPropertyBag.ContractUsesPropertyBag = true;
        }

        /// <summary>
        /// The Property Bag Expander collapsed event handler
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument provided by the sender</param>
        private void ExpanderPropertyBag_Collapsed(object sender, RoutedEventArgs e)
        {
            //set a flag
            this.ViewPropertyBag.ContractUsesPropertyBag = false;
        }

        #endregion

        #region IDialogBase Members

        private EventHandler<EventArgs> _selectedHandler;
        private object _selectedHandlerLocker = new object();

        /// <summary>
        /// Event that an item has been selected from the dialog.
        /// </summary>
        public event EventHandler<EventArgs> ItemSelected
        {
            add
            {
                lock (_selectedHandler)
                {
                    _selectedHandler += value;
                }
            }
            remove
            {
                lock (_selectedHandler)
                {
                    _selectedHandler -= value;
                }
            }
        }

        /// <summary>
        /// Implicit implementation of the dialog base ShowDialog method. Shows the dialog.
        /// </summary>
        /// <returns></returns>
        bool MVC4WPF.Automation.Dialog.IDialogBase.ShowDialog()
        {
            //show the dialog
            bool? result = this.ShowDialog();

            //return false by default
            return result.GetValueOrDefault(false);
        }

        #endregion

        #region IContractDialog Members

        #region Property - BackgroundBrush

        //Local variable for property BackgroundBrush
        private Brush _backgroundBrush = new SolidColorBrush();

        /// <summary>
        /// The brush to display on the background of the dialog.
        /// </summary>
        public Brush BackgroundBrush
        {
            get
            {
                return _backgroundBrush;
            }

            set
            {
                OnPropertyChanging("BackgroundBrush");

                _backgroundBrush = value;

                OnPropertyChanged("BackgroundBrush");
            }
        }
        #endregion Property - BackgroundBrush

        #endregion

        #region Helper Methods

        /// <summary>
        /// Raised the on selected event so that subscribers can do any processing they wish
        /// </summary>
        private void OnSelected()
        {
            if (_selectedHandler != null)
            {
                _selectedHandler.Invoke(this, new EventArgs());
            }
        }
        #endregion

        #region Implementation of INotifyPropertyChanged and INotifyPropertyChanging

        #region Implementation of event - PropertyChanged

        /// <summary>
        /// Local variable that is the event handler for the event 'PropertyChanged'.
        /// </summary>
        private System.ComponentModel.PropertyChangedEventHandler _propertyChanged;

        /// <summary>
        /// Local variable that is the lock object for the event 'PropertyChanged', this is included for thread safety.
        /// </summary>
        private object _propertyChangedEventLock = new object();

        /// <summary>
        /// Event that gets fired every time an a property has been changed on the controller.
        /// </summary>
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                lock (_propertyChangedEventLock)
                {
                    _propertyChanged += value;
                }
            }

            remove
            {
                lock (_propertyChangedEventLock)
                {
                    _propertyChanged -= value;
                }
            }
        }

        /// <summary>
        /// Raises the property changed event synchronously. The event will only be raised if there are subscribers to the event.
        /// </summary>
        /// <param name="propertyName">The name of the property that changed</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this._propertyChanged != null)
            {
                this._propertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Helper method that is to be called by IDisposable to release the event 'PropertyChanged' and supporting resources.
        /// </summary>
        private void CleanupPropertyChangedEvent()
        {
            try
            {
                _propertyChanged = null;

                _propertyChangedEventLock = null;
            }

            catch
            {
            }
        }

        #endregion

        #region Implementation of event - PropertyChanging

        /// <summary>
        /// Local variable that is the event handler for the event 'PropertyChanging'.
        /// </summary>
        private System.ComponentModel.PropertyChangingEventHandler _propertyChanging;

        /// <summary>
        /// Local variable that is the lock object for the event 'PropertyChanging', this is included for thread safety.
        /// </summary>
        private object _propertyChangingEventLock = new object();

        /// <summary>
        /// Event that gets fired every time a property is about to get changed in the controller.
        /// </summary>
        public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging
        {
            add
            {
                lock (_propertyChangingEventLock)
                {
                    _propertyChanging += value;
                }
            }

            remove
            {
                lock (_propertyChangingEventLock)
                {
                    _propertyChanging -= value;
                }
            }
        }

        /// <summary>
        /// Raises the property changing event synchronously. The event will only be raised if there are subscribers to the event.
        /// </summary>
        /// <param name="propertyName">The name of the property that is changing</param>
        protected virtual void OnPropertyChanging(string propertyName)
        {
            if (this._propertyChanging != null)
            {
                this._propertyChanging.Invoke(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Helper method that is to be called by IDisposable to release the event 'PropertyChanging' and supporting resources.
        /// </summary>
        private void CleanupPropertyChangingEvent()
        {
            try
            {
                _propertyChanging = null;

                _propertyChangingEventLock = null;
            }
            catch
            {
            }
        }

        #endregion

        #endregion

        #region IViewPropertyBag<ContractDialogPropertyBag> Members

        #region Property - ViewPropertyBag
        //Local variable for property ViewPropertyBag
        private ContractDialogPropertyBag _viewPropertyBag = new ContractDialogPropertyBag();

        /// <summary>
        /// The property bag for the contract dialog
        /// </summary>
        public ContractDialogPropertyBag ViewPropertyBag
        {
            get
            {
                return _viewPropertyBag;
            }

            set
            {
                OnPropertyChanging("ViewPropertyBag");

                _viewPropertyBag = value;

                OnPropertyChanged("ViewPropertyBag");
            }
        }
        #endregion Property - ViewPropertyBag

        #endregion
    }
}